﻿using System.ComponentModel.DataAnnotations.Schema;
using System.Text.RegularExpressions;
using Core.Domain.Contracts;
using Core.Domain.Events;

namespace Core.Domain.Entities;

[Table("Roles")]
public class Role : AuditableEntity, IAggregateRoot
{
    public string Code { get; private set; } = null!;
    public string Name { get; private set; } = null!;

    private readonly List<RolePermission> _permissions = new();
    public virtual IReadOnlyCollection<RolePermission> Permissions => _permissions.AsReadOnly();
    public virtual ICollection<UserRole> UserRoles { get; private set; } = new List<UserRole>();

    //  编码规则校验
    private static readonly Regex CodePattern = new(@"^(?i)[a-z]+$");

    /// <summary>
    /// 构造器 + 工厂方法 
    /// </summary>
    private Role() { }   // EF Core 用

    private Role(string code, string name, string? description = null, int? sort = 0, bool? enable = false)
    {
        Code = code;
        Name = name;
        Description = description;
        Sort = sort;
        Enabled = enable;
        QueueDomainEvent(new PermissionCodeChanged(code, name));
    }

    public static Role Create(string code, string name, string? description = null, int? sort = 0, bool? enable = true)
    {
        if (!CodePattern.IsMatch(code))
            throw new BoilerplateException("角色编码必须为字母");
        if (string.IsNullOrWhiteSpace(name))
            throw new BoilerplateException("角色名称不能为空");

        return new Role(code, name, description, sort, enable);
    }

    // 改名
    public void Rename(string newName)
    {
        if (string.IsNullOrWhiteSpace(newName))
            throw new BoilerplateException("角色名称不能为空");
        Name = newName;
        QueueDomainEvent(new RoleRenamed(Code, newName));
    }

    public void Recode(string newCode)
    {
        if (string.IsNullOrWhiteSpace(newCode))
            throw new BoilerplateException("编码不能为空");
        Code = newCode;
    }

    // 修改描述
    public void ChangeDescription(string? newDesc)
    {
        Description = newDesc;
        QueueDomainEvent(new RoleDescriptionChanged(Code, newDesc));
    }

    // 权限分配（去重 + 幂等）
    public void AssignPermission(Permission permission)
    {
        if (_permissions.Any(rp => rp.PermissionId == permission.Id))
            return; // 已拥有则忽略

        _permissions.Add(new RolePermission(this, permission));
        QueueDomainEvent(new PermissionAssignedToRole(Code, permission.Code));
    }

    // 撤销权限
    public void RevokePermission(Permission permission)
    {
        var rp = _permissions.FirstOrDefault(rp => rp.PermissionId == permission.Id);
        if (rp is null) return;

        _permissions.Remove(rp);
        QueueDomainEvent(new PermissionRevokedFromRole(Code, permission.Code));
    }

    private void Disable()
    {
        if (Enabled.HasValue && !Enabled.Value) return;
        Enabled = false;
        QueueDomainEvent(new RoleDisabled(Code));
    }

    private void Enable()
    {
        if (Enabled.HasValue && Enabled.Value) return;
        Enabled = true;
        QueueDomainEvent(new RoleEnabled(Code));
    }

    public void SetEnabled(bool enabled)
    {
        if (enabled)
            Enable();
        else
            Disable();
    }
}
